#include "StdAfx.h"
#include "MaterialCompiler.h"
#include "LitCScriptParser.h"
#include "MaterialTemplateGenerator.h"

namespace Lit
{
	namespace Editor
	{
		namespace Material
		{
			std::string Compiler::DEFAULT_RESOURCE_GROUP = "MaterialCompiler";
			Compiler::Compiler(void)
				: mResGroup( DEFAULT_RESOURCE_GROUP )
			{
			}
			Compiler::~Compiler(void)
			{
			}
			std::string extractName( const std::string &text, const std::string &keyword )
			{
				std::string ret;
				Ogre::StringVector lines(Ogre::StringUtil::split( text, "\r\n" ));
				for( auto i=lines.begin(); i!=lines.end(); i++ )
				{
					std::string line((*i));
					size_t p=line.find_first_of("//");
					if( p != std::string::npos )
					{
						line = line.substr( 0, p );
					}
					p = line.find(keyword);
					if( p != std::string::npos )
					{
						ret = line.substr( p+keyword.size(), line.size()-(p+keyword.size()) );
						Ogre::StringUtil::trim( ret );
						break;
					}
				}
				ret = Ogre::StringUtil::replaceAll( ret, "\n", "" );
				ret = Ogre::StringUtil::replaceAll( ret, "{", "" );
				ret = Ogre::StringUtil::replaceAll( ret, "\"", "" );
				return ret;
			}
			void Compiler::setResourceGroup( const std::string &name )
			{
				mResGroup = name;
			}
			const std::string &Compiler::getResourceGroup() const
			{
				return mResGroup;
			}
			bool Compiler::matchesExtension( const std::string &name, const std::string &ext ) const
			{
				return Ogre::StringUtil::endsWith( name, "."+ext, false );
			}
			Ogre::GpuProgramPtr Compiler::compileProgram( const std::string &name, const std::string &text )
			{
				static Ogre::ResourceGroupManager * mgr = Ogre::ResourceGroupManager::getSingletonPtr();
				if( !mgr->resourceGroupExists( mResGroup ) ) 
					mgr->createResourceGroup( mResGroup );
				mgr->clearResourceGroup( mResGroup );
				
				Ogre::LogManager::getSingleton().logMessage( "Compiling '"+name+"'" );

				Ogre::GpuProgramPtr prog;
				if( matchesExtension( name, "program" ) )
				{
					Ogre::DataStreamPtr strm( new Ogre::MemoryDataStream( FilePath(name), (void*)&text.at(0), text.size()*sizeof(char), false, true ) );
					Ogre::GpuProgramManager::getSingleton().parseScript( strm, mResGroup );
					prog = Ogre::GpuProgramManager::getSingleton().getByName(FilePath(name).fileName());
					if( !prog.isNull() && !prog->isLoaded() )
					{
						prog->load();
					}
				}
				return prog;
			}
			Ogre::MaterialPtr Compiler::compileMaterial( const std::string &name, const std::string &text )
			{
				static Ogre::ResourceGroupManager * mgr = Ogre::ResourceGroupManager::getSingletonPtr();
				if( !mgr->resourceGroupExists( mResGroup ) ) 
					mgr->createResourceGroup( mResGroup );
				mgr->clearResourceGroup( mResGroup );
				
				Ogre::LogManager::getSingleton().logMessage( "Compiling '"+name+"' ("+extractName(text, "material")+"):" );
				Ogre::LogManager::getSingleton().logMessage( "\tExtension found '"+FilePath(name).extension()+"'" );

				std::string matname = extractName(text, "material");
				Ogre::MaterialPtr mat;
				if( matchesExtension( name, "material" ) )
				{
					Ogre::MaterialManager::getSingleton().unload( matname );
					Ogre::MaterialManager::getSingleton().remove( matname );
					Ogre::DataStreamPtr strm( new Ogre::MemoryDataStream( name, (void*)&text.at(0), text.size()*sizeof(char), false, true ) );
					Ogre::MaterialManager::getSingleton().parseScript( strm, mResGroup );
					mat = Ogre::MaterialManager::getSingleton().getByName(matname);
					if( mat.isNull() ) Ogre::LogManager::getSingleton().logMessage("\tInvalid material" );
					else
					{
						mat->compile();
						if( !mat->isLoaded() ) mat->load();
						Ogre::LogManager::getSingleton().logMessage("\tMaterial '"+mat->getName()+"' successsfully compiled" );
					}
				}
				return mat;
			}
		};
	};
};